package com.whjfxx.terminal.config;

import com.whjfxx.terminal.commons.Result;
import com.whjfxx.terminal.exceptions.BizException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.util.Objects;
import java.util.StringJoiner;

/**
 * 全局异常处理
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 业务处理，可能会抛出这个异常
     * @param e
     * @return
     */
    @ExceptionHandler(BizException.class)
    @ResponseBody
    public Result<Object> exceptionHandler(BizException e) {
        log.warn("bizException : {}", e);
        Result<Object> result = new Result<>();
        result.setCode(e.getCode());
        result.setMsg(e.getMessage());
        return result;
    }

    /**
     * \@Validated 注解验证失败，会抛出这个异常
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Result<Object> exceptionHandler(MethodArgumentNotValidException e) {
        StringBuffer msg = new StringBuffer();
        e.getBindingResult().getAllErrors().forEach(obj -> msg.append(obj.getDefaultMessage()).append(";"));
        if (msg.length() > 1) {
            msg.deleteCharAt(msg.length() - 1);
        }
        log.info("param error 2 ->{}", e);
        Result<Object> result = new Result<>();
        result.setCode("10101");
        result.setMsg(msg.toString());
        return result;
    }

    /**
     * 调用方法参数错误，可能会抛出这个异常
     * @param e
     * @return
     */
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public Result<Object> exceptionHandler(IllegalArgumentException e) {
        log.info("param error 3 ->{}", e);
        Result<Object> result = new Result<Object>();
        result.setCode("10101");
        result.setMsg(e.getMessage());
        return result;
    }

    /**
     * Validated校验失败时返回message信息,多个message中间用 | 分隔
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public Result<Object> exceptionHandler(BindException e) {
        String msg = e.getFieldErrors().stream()
            .reduce(new StringJoiner("|"), (sj, f) -> sj.add(f.getDefaultMessage()), (a, b) -> a).toString();
        log.info("param error 5 ->{}", e);
        Result<Object> result = new Result<>();
        result.setCode("10102");
        result.setMsg(Objects.toString(msg, "API调用错误"));
        result.setData(e.getMessage());
        return result;
    }

    /**
     * 在方法上加验证注解，会抛出下面的异常，如：
     * test3(@NotNull(message = "不能为空") String tt)
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result<Object> exceptionHandler(ConstraintViolationException e) {
        log.info("param error 6 ->{}", e);
        Result<Object> result = new Result<>();
        result.setCode("10101");
        result.setMsg(e.getMessage());
        return result;
    }

    /**
     * 缺省异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public Result<Object> exceptionHandler(Exception e) {
        log.error("system error->" + e.getMessage(), e);
        Result<Object> result = new Result<>();
        result.setCode("10002");
        result.setMsg("系统错误");
        result.setData(e.getMessage());
        return result;
    }

}
